from src.baseapp.controller.baseController import BaseController
from src.baseapp.model.BaseOrmOpeator import OrmOperator
from src.baseapp.model.testcaseServiceModel.testPlanModel import PlanModel
from src.baseapp.model.testcaseServiceModel.planTestcaseMappingModel import PlanTestcaseMappingModel
from src.baseapp.model.testcaseServiceModel.testcaseModel import TestCaseModel
from src.error.exceptions import PlanNotFoundException
from typing import List


class PlanController(BaseController):
    def __init__(self):
        super().__init__()
        self.orm = OrmOperator(PlanModel)
        self.plan_testcase_orm = OrmOperator(PlanTestcaseMappingModel)

    def add_plan(self, plan_info: dict):
        """
        添加测试计划
        :param plan_info: 测试计划信息
        :return:
        """
        response = self.response_data()
        try:
            plan: PlanModel = PlanModel(**plan_info)
            self.orm.insert_data(plan)
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def delete_plan(self, plan_id: int):
        """
        删除测试计划
        :param plan_id: 测试计划ID
        :return:
        """
        response = self.response_data()
        try:
            plan = self.orm.equal(PlanModel.id, plan_id).equal(PlanModel.is_delete, 0).get_one()
            if not plan:
                raise PlanNotFoundException(f"测试计划ID为{plan_id}的测试计划不存在")
            plan.is_delete = 1
            self.orm.update_data(plan)
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def update_plan(self, plan_ids: List[int], plan_info: dict):
        """
        更新测试计划
        :param plan_ids: 测试计划ID
        :param plan_info: 测试计划信息
        :return:
        """
        response = self.response_data()
        try:
            plans = self.orm.in_here(PlanModel.id, plan_ids).equal(PlanModel.is_delete, 0).get_all()
            for plan in plans:
                for key, value in plan_info.items():
                    setattr(plan, key, value)
            self.orm.update_data(plans)
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def get_plan_list(self, condition: dict):
        """
        获取测试计划列表
        :param condition: 查询条件
        :return:
        """
        field_condition_mapping = {
            "plan_id": PlanModel.plan_id,
            "plan_name": PlanModel.plan_name,
            "project_id": PlanModel.project_id,
            "plan_status": PlanModel.plan_status,
            "create_user_id": PlanModel.create_user_id,
            "create_time": PlanModel.create_time,
            "update_time": PlanModel.update_time,
            "is_delete": PlanModel.is_delete,
        }
        response = self.response_data()
        if condition.get('is_delete'):
            condition['is_delete'] = 0
        try:
            for key, value in condition.items():
                if key == 'plan_name':
                    self.orm = self.orm.like(field_condition_mapping[key], value)
                elif key == 'project_id':
                    self.orm = self.orm.in_here(field_condition_mapping[key], value)
                elif key == 'plan_status':
                    self.orm = self.orm.in_here(field_condition_mapping[key], value)
                elif key in ("update_time", "create_time"):
                    self.orm = self.orm.between(field_condition_mapping[key], value[0], value[1])
                else:
                    self.orm = self.orm.equal(field_condition_mapping[key], value)
            else:
                plans = self.orm.get_all()
                response.data['plans'] = [
                    {
                        "plan_id": plan.plan_id,
                        "plan_name": plan.plan_name,
                        "project_id": plan.project_id,
                        "plan_pre_start_time": plan.plan_pre_start_time,
                        "plan_pre_end_time": plan.plan_pre_end_time,
                        "plan_actual_start_time": plan.plan_actual_start_time,
                        "plan_actual_end_time": plan.plan_actual_end_time,
                        "plan_status": plan.plan_status,
                        "create_user_id": plan.create_user_id,
                        "create_time": plan.create_time,
                        "update_time": plan.update_time,
                    }
                    for plan in plans
                ]
            plans = self.orm.get_all()
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def get_plan_info(self, plan_id: int):
        """
        获取测试计划信息
        :param plan_id: 测试计划ID
        :return:
        """
        response = self.response_data()
        try:
            plan = self.orm.equal(PlanModel.plan_id, plan_id).equal(PlanModel.is_delete, 0).get_one()
            if not plan:
                raise PlanNotFoundException(f"测试计划ID为{plan_id}的测试计划不存在")
            cases = self.plan_testcase_orm.\
                join(TestCaseModel, PlanTestcaseMappingModel.testcase_id == TestCaseModel.testcase_id).\
                equal(PlanTestcaseMappingModel.plan_id, plan_id).get_all()
            response.data['plan'] = {
                "plan_id": plan.plan_id,
                "plan_name": plan.plan_name,
                "project_id": plan.project_id,
                "plan_description": plan.plan_description,
                "plan_pre_start_time": plan.plan_pre_start_time,
                "plan_pre_end_time": plan.plan_pre_end_time,
                "plan_actual_start_time": plan.plan_actual_start_time,
                "plan_actual_end_time": plan.plan_actual_end_time,
                "plan_status": plan.plan_status,
                "create_user_id": plan.create_user_id,
                "create_time": plan.create_time,
                "update_time": plan.update_time,
            }
            response.data['plan']['cases'] = [
                {
                    "testcase_id": case.testcase_id,
                    "name": case.name,
                    "priority": case.priority,
                    "creator": case.user_id,
                    "create_time": case.create_time,
                    "update_time": case.update_time,
                }
                for case in cases
            ]
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def update_plan_status(self, plan_id: int, plan_status: int):
        """
        更新测试计划状态
        :param plan_id: 测试计划ID
        :param plan_status: 测试计划状态
        :return:
        """
        response = self.response_data()
        try:
            plan = self.orm.equal(PlanModel.plan_id, plan_id).equal(PlanModel.is_delete, 0).get_one()
            if not plan:
                raise PlanNotFoundException(f"测试计划ID为{plan_id}的测试计划不存在")

            state_machine = PlanStateMachine(plan.plan_status)
            if not state_machine.transition(plan_status):
                response.msg = f"无法从状态 {plan.plan_status} 转换到状态 {plan_status}"
                response.code = 400
                return response.code, response.to_dict
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def add_testcase_to_plan(self, plan_id: int, testcase_ids: List[int]):
        """
        添加测试用例到测试计划
        :param plan_id: 测试计划ID
        :param testcase_ids: 测试用例ID列表
        :return:
        """
        response = self.response_data()
        try:
            plans_case = [
                PlanTestcaseMappingModel(plan_id=plan_id, testcase_id=testcase_id)
                for testcase_id in testcase_ids
            ]
            self.plan_testcase_orm.insert_data(plans_case)
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def remove_testcase_from_plan(self, plan_id: int, testcase_ids: List[int]):
        """
        从测试计划中移除测试用例
        :param plan_id: 测试计划ID
        :param testcase_ids: 测试用例ID列表
        :return:
        """
        response = self.response_data()
        try:
            plan_cases = self.plan_testcase_orm.equal(PlanTestcaseMappingModel.plan_id, plan_id).in_here(
                PlanTestcaseMappingModel.testcase_id, testcase_ids).get_all()
            self.plan_testcase_orm.delete_data(plan_cases)
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict

    def update_testcase_status(self, plan_id: int, testcase_ids: List[int], status: int, remark: str = None):
        """
        更新测试用例状态
        :param plan_id: 测试计划ID
        :param testcase_ids: 测试用例ID列表
        :param status: 测试用例状态
        :param remark: 备注
        :return:
        """
        response = self.response_data()
        try:
            plan_cases = self.plan_testcase_orm.equal(PlanTestcaseMappingModel.plan_id, plan_id).in_here(
                PlanTestcaseMappingModel.testcase_id, testcase_ids).get_all()
            for plan_case in plan_cases:
                plan_case.status = status
                plan_case.remark = remark
            self.plan_testcase_orm.update_data(plan_cases)
        except Exception as e:
            response.msg = str(e)
            response.code = 500
        return response.code, response.to_dict


class PlanStateMachine:
    def __init__(self, initial_state):
        self.state = initial_state

    def transition(self, new_state):
        if self.can_transition(new_state):
            self.state = new_state
            return True
        return False

    def can_transition(self, new_state):
        # 定义允许的状态转换
        allowed_transitions = {
            0: [1, 3, 4],  # 未开始 -> 进行中, 已暂停, 已取消
            1: [2, 3, 4],  # 进行中 -> 已完成, 已暂停, 已取消
            2: [],  # 已完成 -> 无法变更
            3: [1, 4],  # 已暂停 -> 进行中, 已取消
            4: []  # 已取消 -> 无法变更
        }
        return new_state in allowed_transitions.get(self.state, [])
